#ifndef JSCRIPTEDITOR_H
#define JSCRIPTEDITOR_H

#include <QMainWindow>
#include "ui_JScriptEditor.h"
#include "PythonQt.h"
#include <QWidget>
#include <QTextEdit>
#include <QTextBlockUserData>
#include <QHBoxLayout>
#include <QCompleter>
#include <QStack>

class JScriptConsole;
class JScriptHighlighter;
class JScriptEdit;
class LineNumberPanel;
class CodeFoldPanel;

typedef enum _FoldType {
	FOLD_OFF = 0, 
	FOLD_SINGLELINECOMMENT, 
	FOLD_MULTILINECOMMENT,
	FOLD_STRING,
	FOLD_CHAR
} ;

class JScriptEditor : public QMainWindow
{
	Q_OBJECT

public:
	JScriptEditor(JScriptConsole* console, QWidget *parent = 0);
	~JScriptEditor();

private:
	Ui::JScriptEditorClass ui;
	QHBoxLayout* m_layout;
	JScriptEdit* m_editor;
	LineNumberPanel* m_lines;
	CodeFoldPanel* m_folds;
	JScriptConsole* m_console;
};

class JScriptEdit : public QTextEdit
{
	Q_OBJECT

public:
	JScriptEdit(QWidget *parent, const PythonQtObjectPtr& context, JScriptConsole* console);
	~JScriptEdit();

public slots:
	void keyPressEvent(QKeyEvent *e);
	void insertCompletion(const QString&);

private slots:
	void slotCursorPositionChanged();
	void slotViewportUpdate();
	void selectionListener();

protected:
	void handleCompleterMenu();

private:
	void braceMatching();
	void paintEvent(QPaintEvent *);

	JScriptHighlighter* m_highlighter;
	PythonQtObjectPtr m_context;
	JScriptConsole *m_console;
	QCompleter* m_completer;
	_FoldType FoldType;
};

class JScriptEditPanel : public QWidget
{
public:
	JScriptEditPanel(QWidget *p = 0): QWidget(p), pEdit(0) {}
	virtual ~JScriptEditPanel(){}

	QTextEdit * editor() {return pEdit;}
	void attach(QTextEdit *e);

protected:
	virtual void paintEvent(QPaintEvent *e);
	virtual void paint(QPainter *p, QTextEdit *e) = 0;

private:
	QTextEdit *pEdit;
};

struct QBlockData;
struct QFoldedText
{
	QFoldedText() {}

	~QFoldedText() { lines.clear(); }

	inline void addLine(QString b, QBlockData *t)
	{ lines << qMakePair(b, t); }

	QList< QPair<QString, QBlockData*> > lines;
};

struct QBlockData : public QTextBlockUserData
{
	inline QBlockData() :
	folded(0), collapsedBlock(0), marked(false)
	{}

	~QBlockData() { }

	static QBlockData* data(const QTextBlock& block)
	{ return dynamic_cast<QBlockData *>(block.userData()); }

	void setToBlock(QTextBlock & block)
	{ block.setUserData(this); }

	bool marked;
	QFoldedText *folded;
	int userState;
	int collapsedBlock;
};

class LineNumberPanel : public JScriptEditPanel
{
public:
	LineNumberPanel(QWidget *p = 0);
	virtual ~LineNumberPanel() {}

	void setColor( QColor & color );
	QColor getColor();
	void setTextColor( QColor & color );
	QColor getTextColor();

protected:
	virtual void paint(QPainter *p, QTextEdit *e);

private:

};

class CodeFoldPanel : public JScriptEditPanel
{
public:
	CodeFoldPanel(QWidget *p = 0);
	virtual ~CodeFoldPanel();

	void setColor( QColor & color );
	QColor getColor();
	void setTextColor( QColor & color );
	QColor getTextColor();	

	void expandAll();

	bool collapsed(QTextBlock & b);
	void expand(QTextBlock & b);
	
	void mouseclk(QTextBlock & b);
protected:
	virtual void mousePressEvent(QMouseEvent *e);
	virtual void paint(QPainter *p, QTextEdit *e);

	QRect drawIcon(	QPainter *p, QTextEdit *e,
		int x, int y, bool expand);
	void match(QTextEdit *e);
	void setBlockUserState(  QTextBlock & b, int state );
	int BlockUserState( const QTextBlock & b );
private:
	//QColor TextColor;
	_FoldType FoldType;
	QMap<QTextBlock, QRect> collapsable;
};

#endif // JSCRIPTEDITOR_H
